# -*- coding: utf-8 -*-
"""
用户组管理控制器
提供用户组的创建、删除、更新、查询等功能
支持用户组权限管理和过期时间设置
"""
import uuid
from datetime import datetime
from typing import Optional

from loguru import logger
from pydantic import BaseModel
from fastapi import Request

from db.repository.user import (
    db_get_groups_for_superadmin,
    db_get_groups_for_user,
    filter_groups_by_name,
    db_get_group_by_id,
)
from db.repository.user_group import (
    db_check_group_name_exists,
    db_create_group,
    db_add_user_to_group,
    db_remove_all_users_from_group,
    db_soft_delete_group,
    db_check_user_group_permission,
    db_get_group_users,
    db_update_group_info,
    db_remove_user_from_group,
    db_get_group_permissions,
    db_set_group_expiration,
    db_add_group_resource,
    db_get_group_knowledge_bases,
    db_get_group_clauses,
)
from schemas.response_entity import JsonModel


# ==================== 数据模型定义 ====================

class GroupEntity(BaseModel):
    """用户组创建实体"""
    name: str  # 用户组名称
    description: Optional[str] = None  # 用户组描述
    token: str  # 用户token
    expiration_time: Optional[datetime] = None  # 过期时间


class GroupDelEntity(BaseModel):
    """用户组删除实体"""
    token: str  # 用户token
    group_id: int  # 用户组ID


class GroupUpdateEntity(BaseModel):
    """用户组更新实体"""
    token: str  # 用户token
    group_id: int  # 用户组ID
    name: Optional[str] = None  # 新的用户组名称
    description: Optional[str] = None  # 新的用户组描述
    expiration_time: Optional[datetime] = None  # 新的过期时间


class GroupUserEntity(BaseModel):
    """用户组用户操作实体"""
    token: str  # 用户token
    group_id: int  # 用户组ID
    user_id: int  # 用户ID


class GroupPermissionEntity(BaseModel):
    """用户组权限实体"""
    token: str  # 用户token
    group_id: int  # 用户组ID
    permission_id: int  # 权限ID


class GroupExpirationEntity(BaseModel):
    """用户组过期时间设置实体"""
    token: str  # 用户token
    group_id: int  # 用户组ID
    expiration_time: datetime  # 过期时间


# 
class AddGroupResourceEntity(BaseModel):
    token: str
    group_id: int
    kb_id_list: list[uuid.UUID] = []
    clause_id_list: list[uuid.UUID] = []


# ==================== API接口函数 ====================

# 获取用户组列表
async def get_list_group(request: Request, token: str, group_name: str = None):
    """
    获取用户组列表

    Args:
        request: FastAPI请求对象
        token: 用户认证token
        group_name: 可选的组名过滤条件

    Returns:
        JsonModel: 包含用户组列表的响应

    功能说明:
        - 超级管理员可查看所有用户组
        - 普通用户只能查看自己所属的用户组
        - 支持按组名进行模糊搜索
    """
    user = request.state.user
    if user is None:
        return JsonModel(code=401, data=None, msg="用户token 非法").to_response()

    try:
        # 根据用户角色获取不同的用户组列表
        if user.check_superman_role():
            groups = db_get_groups_for_superadmin()
        else:
            groups = db_get_groups_for_user(user.id)

        # 按组名过滤
        user_groups = filter_groups_by_name(groups, group_name)
        result = []
        for group in user_groups:
            group_data = group.to_json()
            # 标记是否为组创建者
            group_data["owner"] = group_data.get("owner") == user.id
            result.append(group_data)

        return JsonModel(code=200, data=result, msg="success").to_response()
    except Exception as e:
        logger.error(f"获取用户组列表失败: {str(e)}")
        return JsonModel(code=500, data=None, msg="服务器内部错误").to_response()


# 创建用户组
async def post_add_group(request: Request, payload: GroupEntity):
    """
    创建用户组

    Args:
        request: FastAPI请求对象
        payload: 用户组创建数据

    Returns:
        JsonModel: 创建结果响应

    功能说明:
        - 检查组名是否已存在
        - 创建新的用户组
        - 自动将创建者加入组
        - 支持设置过期时间
    """
    user = request.state.user
    if user is None:
        return JsonModel(code=401, data=None, msg="用户token 非法").to_response()

    try:
        # 检查组名是否已存在
        existing_group = db_check_group_name_exists(payload.name)
        if existing_group:
            return JsonModel(code=400, data=None, msg=f"用户组:{payload.name}已存在,请更换用户组名").to_response()

        # 创建新组
        group = db_create_group(payload.name, payload.description, user.id, payload.expiration_time)
        if not group:
            return JsonModel(code=500, data=None, msg="创建用户组失败").to_response()

        # 将创建者加入组
        db_add_user_to_group(user.id, group.id)

        return JsonModel(code=200, data=None, msg=f"用户组:{payload.name}创建成功").to_response()
    except Exception as e:
        logger.error(f"创建用户组失败: {str(e)}")
        return JsonModel(code=500, data=None, msg="服务器内部错误").to_response()


# 删除用户组
async def delete_group(request: Request, payload: GroupDelEntity):
    """
    删除用户组

    Args:
        request: FastAPI请求对象
        payload: 用户组删除数据

    Returns:
        JsonModel: 删除结果响应

    功能说明:
        - 只有超级管理员或组创建者可以删除组
        - 删除前会移除组内所有用户关联
        - 使用软删除方式，不会物理删除数据
    """
    user = request.state.user
    if user is None:
        return JsonModel(code=401, data=None, msg="用户token 非法").to_response()

    try:
        group = db_get_group_by_id(payload.group_id, user)
        if not group:
            return JsonModel(code=404, data=None, msg="用户组未找到").to_response()

        # 检查是否有权限删除
        if not user.check_superman_role() and group.owner != user.id:
            return JsonModel(code=403, data=None, msg="无权限删除此用户组").to_response()

        # 删除组内所有用户关联
        db_remove_all_users_from_group(payload.group_id)

        # 软删除组
        db_soft_delete_group(payload.group_id)

        return JsonModel(code=200, data=None, msg=f"用户组{group.name}已被删除").to_response()
    except Exception as e:
        logger.error(f"删除用户组失败: {str(e)}")
        return JsonModel(code=500, data=None, msg="服务器内部错误").to_response()


# 获取组内用户列表
async def get_list_group_users(request: Request, group_id: int, username: str = None):
    """
    获取组内用户列表

    Args:
        request: FastAPI请求对象
        group_id: 用户组ID
        username: 可选的用户名过滤条件

    Returns:
        JsonModel: 包含组内用户列表的响应

    功能说明:
        - 只有组内成员可以查看组内用户列表
        - 支持按用户名进行模糊搜索
        - 返回用户的基本信息
    """
    user = request.state.user
    if user is None:
        return JsonModel(code=401, data=None, msg="用户token 非法").to_response()

    try:
        group = db_get_group_by_id(group_id, user)
        if not group:
            return JsonModel(code=404, data=[], msg="用户组未找到").to_response()

        if user.check_superman_role():
            users = db_get_group_users(group_id)  # noqa
            data = [user_info.to_json() for user_info in users]
            return JsonModel(code=200, data=data, msg="success").to_response()

        # 检查用户是否有权限查看此组
        if not db_check_user_group_permission(user.id, group_id):
            return JsonModel(code=403, data=[], msg="无权限查看此用户组").to_response()

        users = db_get_group_users(group_id, username)  # noqa
        data = [user_info.to_json() for user_info in users]

        return JsonModel(code=200, data=data, msg="success").to_response()
    except Exception as e:
        logger.error(f"获取组内用户列表失败: {str(e)}")
        return JsonModel(code=500, data=None, msg="服务器内部错误").to_response()


# 更新用户组信息
async def update_group_info(request: Request, payload: GroupUpdateEntity):
    """
    更新用户组信息

    Args:
        request: FastAPI请求对象
        payload: 用户组更新数据

    Returns:
        JsonModel: 更新结果响应

    功能说明:
        - 只有超级管理员或组创建者可以更新组信息
        - 支持更新组名、描述和过期时间
        - 所有字段都是可选的
    """
    user = request.state.user
    if user is None:
        return JsonModel(code=401, data=None, msg="用户token 非法").to_response()

    try:
        group = db_get_group_by_id(payload.group_id, user)
        if not group:
            return JsonModel(code=404, data=None, msg="用户组未找到").to_response()

        # 检查是否有权限更新
        if not user.check_superman_role() and group.owner != user.id:
            return JsonModel(code=403, data=None, msg="无权限更新此用户组").to_response()

        # 更新组信息
        db_update_group_info(payload.group_id, payload.name, payload.description, payload.expiration_time)

        return JsonModel(code=200, data=None, msg="用户组更新成功").to_response()
    except Exception as e:
        logger.error(f"更新用户组失败: {str(e)}")
        return JsonModel(code=500, data=None, msg="服务器内部错误").to_response()


# 从组中删除用户
async def group_delete_user(request: Request, payload: GroupUserEntity):
    """
    从组中删除用户

    Args:
        request: FastAPI请求对象
        payload: 用户组用户操作数据

    Returns:
        JsonModel: 删除结果响应

    功能说明:
        - 只有超级管理员或组创建者可以移除用户
        - 移除用户与组的关联关系
        - 不会删除用户本身
    """
    user = request.state.user
    if user is None:
        return JsonModel(code=401, data=None, msg="用户token 非法").to_response()

    try:
        group = db_get_group_by_id(payload.group_id, user)
        if not group:
            return JsonModel(code=404, data=None, msg="用户组未找到").to_response()

        # 检查是否有权限操作
        if not user.check_superman_role() and group.owner != user.id:
            return JsonModel(code=403, data=None, msg="无权限操作此用户组").to_response()

        # 删除用户组关联
        db_remove_user_from_group(payload.user_id, payload.group_id)

        return JsonModel(code=200, data=None, msg="用户已从组中移除").to_response()
    except Exception as e:
        logger.error(f"从组中删除用户失败: {str(e)}")
        return JsonModel(code=500, data=None, msg="服务器内部错误").to_response()


# 获取组权限列表
async def get_list_group_permission(request: Request, group_id: int):
    """
    获取组权限列表

    Args:
        request: FastAPI请求对象
        group_id: 用户组ID

    Returns:
        JsonModel: 包含组权限列表的响应

    功能说明:
        - 只有超级管理员或组创建者可以查看组权限
        - 返回组的所有权限信息
        - 权限信息包括权限ID和权限名称
    """
    user = request.state.user
    if user is None:
        return JsonModel(code=401, data=None, msg="用户token 非法").to_response()

    try:
        group = db_get_group_by_id(group_id, user)
        if not group:
            return JsonModel(code=404, data=[], msg="用户组未找到").to_response()

        # 检查权限
        if not user.check_superman_role() and group.owner != user.id:
            return JsonModel(code=403, data=[], msg="无权限查看此用户组权限").to_response()

        permissions = db_get_group_permissions(group_id)
        return JsonModel(code=200, data=permissions, msg="success").to_response()
    except Exception as e:
        logger.error(f"获取组权限列表失败: {str(e)}")
        return JsonModel(code=500, data=None, msg="服务器内部错误").to_response()


# 设置组过期时间
async def set_group_expiration_time(request: Request, payload: GroupExpirationEntity):
    """
    设置组过期时间

    Args:
        request: FastAPI请求对象
        payload: 用户组过期时间设置数据

    Returns:
        JsonModel: 设置结果响应

    功能说明:
        - 只有超级管理员或组创建者可以设置过期时间
        - 过期时间到达后，组将自动失效
        - 支持设置具体的过期时间点
    """
    user = request.state.user
    if user is None:
        return JsonModel(code=401, data=None, msg="用户token 非法").to_response()

    try:
        group = db_get_group_by_id(payload.group_id, user)
        if not group:
            return JsonModel(code=404, data=None, msg="用户组未找到").to_response()

        # 检查权限
        if not user.check_superman_role() and group.owner != user.id:
            return JsonModel(code=403, data=None, msg="无权限设置此用户组过期时间").to_response()

        # 设置过期时间
        db_set_group_expiration(payload.group_id, payload.expiration_time)

        return JsonModel(code=200, data=None, msg="组过期时间设置成功").to_response()
    except Exception as e:
        logger.error(f"设置组过期时间失败: {str(e)}")
        return JsonModel(code=500, data=None, msg="服务器内部错误").to_response()


# 绑定用户组资源
async def add_group_resource(request: Request, payload: AddGroupResourceEntity):
    """
    实现用户组与数据库、条款的绑定

    Args:
        request: FastAPI请求对象
        payload: 用户组资源绑定数据

    Returns:
        JsonModel: 绑定结果响应
    """
    user = request.state.user
    if user is None:
        return JsonModel(code=401, data=None, msg="用户token 非法").to_response()

    try:
        # 检查用户权限
        if not user.check_superman_role():
            return JsonModel(code=403, data=None, msg="用户权限不够").to_response()

        # 查询用户组
        group = db_get_group_by_id(payload.group_id, user)
        if group is None:
            return JsonModel(code=404, data=None, msg="用户组未找到").to_response()

        # 绑定知识库和条款库
        db_add_group_resource(payload.group_id, payload.kb_id_list, payload.clause_id_list)

        return JsonModel(code=200, data=None, msg="用户组资源绑定成功").to_response()
    except Exception as e:
        logger.error(f"绑定失败: {str(e)}")
        return JsonModel(code=500, data=None, msg="服务器内部错误").to_response()


# 获取用户组资源列表
async def get_group_resource_list(request: Request, group_id: int, rtype: int = 0):
    """
    获取用户组资源列表

    Args:
        request: FastAPI请求对象
        group_id: 用户组ID
        rtype: 资源类型 (0: 知识库, 1: 条款库)

    Returns:
        JsonModel: 资源列表响应
    """
    user = request.state.user
    if user is None:
        return JsonModel(code=401, data=None, msg="用户token 非法").to_response()

    try:
        if not user.check_admin_role():
            return JsonModel(code=403, data=None, msg="用户无权限").to_response()

        # 查询用户组
        group = db_get_group_by_id(group_id, user)
        if not group:
            return JsonModel(code=404, data=None, msg="用户组未找到").to_response()

        if rtype not in [0, 1]:
            return JsonModel(code=400, data=None, msg="类型错误").to_response()

        if rtype == 1:
            # 获取条款库资源
            clauses = db_get_group_clauses(group_id)
            data = []
            for clause in clauses:
                clause_data = {
                    "clause_name": clause.origin_name,
                    "file_id": str(clause.id),
                    "groups": [{"id": group.id, "name": group.name}]
                }
                data.append(clause_data)

            return JsonModel(code=200, data=data, msg="success").to_response()
        else:
            # 获取知识库资源
            kbs = db_get_group_knowledge_bases(group_id)
            data = []
            for kb in kbs:
                kb_data = kb.to_json()
                # 获取知识库关联的所有组信息
                group_info = []
                for g_id in kb.group_ids:
                    group_obj = db_get_group_by_id(g_id, user)
                    if group_obj:
                        group_info.append({"group_id": g_id, "name": group_obj.name})
                kb_data["groups"] = group_info
                data.append(kb_data)

            return JsonModel(code=200, data=data, msg="success").to_response()
    except Exception as e:
        logger.error(f"获取用户组资源列表失败: {str(e)}")
        return JsonModel(code=500, data=None, msg="服务器内部错误").to_response()
